#include "dialog.h"
#include "ui_dialog.h"
#include <QFileDialog>
#include <QMessageBox>
#include <qextserialenumerator.h>
#include <QListWidgetItem>
#include <QListWidget>
#include <QIcon>

//_________________________________________________________________________
Dialog::Dialog(CSplashScreen* aSplashScreen, QWidget *parent) : QDialog(parent), ui(new Ui::Dialog)
{
    Qt::WindowFlags flags = Qt::Window | Qt::WindowMinimizeButtonHint | Qt::WindowCloseButtonHint;
    this->setWindowFlags(flags);
    this->setAttribute(Qt::WA_QuitOnClose);

    int i;
    QString msg;

    ui->setupUi(this);

    // Device discovery agent
    aSplashScreen->showMessage(QString("Searching For Devices..."),
                               Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

    QList<QextPortInfo> ports = QextSerialEnumerator::getPorts();
    // try out all the discoverred ports
    for (i=0; i<ports.size(); i++)
    {
        // try adding that device (non simulated)
        msg.sprintf("Trying to add device#%d.", i);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        CDevice newDevice (ports[i], 0);
        if (newDevice.getDeviceType( )==NOTHING_FOUND)
        {
            continue;
        }

        msg.sprintf("Found %s device.",
                    (newDevice.getDeviceType( )==MOUSSAVI_DEVICE)?MOUSSAVI_PRODUCT_ID:ANIBIKE_PRODUCT_ID);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        m_deviceList.push_back(newDevice);
    }

    // if nothing was found then add a single simulated device
    if (m_deviceList.size()==0)
    {
        aSplashScreen->showMessage(QString("No devices found (simulating)..."),
                                   Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        QextPortInfo port_info;             // make a dummy port info
        CDevice newDevice (port_info, 1);   // make it simulated
        m_deviceList.push_back(newDevice);
    }

    for ( i=0; i<(int)(m_deviceList.size()); i++)
    {
        int result = -1;
        CHardwareParams* pHW_Params = NULL;

        msg.sprintf("Connecting %s(%d) device.",
                    (m_deviceList[i].getDeviceType( )==MOUSSAVI_DEVICE)?MOUSSAVI_PRODUCT_ID:ANIBIKE_PRODUCT_ID,i);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        m_currentEdittedHWFacade = m_deviceList[i].getHardwareFacade();
        m_currentEdittedFileSystem = m_deviceList[i].getFileSystem();

        // while we cant connect the current device node
        while (result==-1)
        {
            result = m_currentEdittedHWFacade->ConnectDevice ();
            if (result==-1)
            {
                QMessageBox msgBox ( QMessageBox::Warning, tr("Connection Problem"),
                                     tr("Could not establish connection with ANIBIKE device."),
                                     QMessageBox::Retry|QMessageBox::Abort);
                msgBox.setInformativeText(tr("Make sure the device is in discoverable range and turned on.\n"
                                             "Would you like to retry?") );
                msgBox.setDefaultButton(QMessageBox::Retry);
                int ret = msgBox.exec();

                if (ret==QMessageBox::Abort)
                {
                    break;
                }
            }
        }

        // if the user chose to abort the connection process or it couldn't connect
        if (result == -1)
        {
            // erase the node
            m_deviceList.removeAt(i);

            // continue to the next node
            continue;
        }

        msg.sprintf("Registering device #%d.", i);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        // try acquiring hardware parameters
        while (pHW_Params==NULL)
        {
            pHW_Params = m_currentEdittedHWFacade->GetParameters();
            if (pHW_Params==NULL)
            {
                QMessageBox msgBox ( QMessageBox::Warning, tr("Connection Problem"),
                                     tr("Could not identify the connected hardware."),
                                     QMessageBox::Retry|QMessageBox::Abort);
                msgBox.setInformativeText(tr("Make sure the device is in discoverable range and turned on.\n"
                                             "Would you like to retry?") );
                msgBox.setDefaultButton(QMessageBox::Retry);
                int ret = msgBox.exec();

                if (ret==QMessageBox::Abort)
                {
                    break;
                }
            }
        }

        if (pHW_Params == NULL)
        {
            // erase the node
            m_deviceList.removeAt(i);

            // continue to the next node
            continue;
        }

        msg.sprintf("Acquiring device #%d.", i);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

        // if everything went well acquire the appropriate file system
        m_deviceList[i].CreateFileSystem (pHW_Params);
        m_currentEdittedFileSystem = m_deviceList[i].getFileSystem();
        unsigned char* data = new unsigned char[ pHW_Params->FlashBlockSizeBytes*
                                        pHW_Params->NumOfBlocksForFrame*3];
        int length;
        int successGettingFS = 0;
        int getFSRetries = 5;

        while ( !successGettingFS && getFSRetries-- )
        {
            // means we found the file system full of stuff
            successGettingFS = m_currentEdittedHWFacade->GetFileSystemRaw (data, &length);

            if (successGettingFS==1)
            {
                if (m_currentEdittedFileSystem->ParseFromRawFS(data, length)==0)    // success
                {
                    break;
                }
                else
                {
                    successGettingFS = 0;
                }
            }
            else if (successGettingFS==2)   // empty
            {
                break;
            }
            else if (getFSRetries==0)
            {
                QMessageBox msgBox ( QMessageBox::Warning, tr("Connection Problem"),
                                     tr("Could not read device files."),
                                     QMessageBox::Retry|QMessageBox::Abort);
                msgBox.setInformativeText(tr("Make sure the device is in discoverable range and turned on.\n"
                                             "Would you like to retry?") );
                msgBox.setDefaultButton(QMessageBox::Retry);
                int ret = msgBox.exec();

                if (ret==QMessageBox::Abort)
                {
                    break;
                }
                else
                {
                    getFSRetries = 5;
                }

            }
        }
        delete []data;

        // set the device number
        m_currentEdittedHWFacade->setDeviceNumber(i);

        msg.sprintf("Device %s(%d) has been added.",
                    (m_deviceList[i].getDeviceType( )==MOUSSAVI_DEVICE)?MOUSSAVI_PRODUCT_ID:ANIBIKE_PRODUCT_ID,i);
        aSplashScreen->showMessage(msg, Qt::AlignBottom | Qt::AlignHCenter, Qt::white);

    }

    // Finished enumeration and discovery
    // Set the first device on the graphic interface
    m_currentEdittedHWFacade = m_deviceList[0].getHardwareFacade();
    m_currentEdittedFileSystem = m_deviceList[0].getFileSystem();
    ui->fileList->SetFileSystem(m_currentEdittedFileSystem);
    ui->fileList->SetCurrentDeviceNumber(0);
    CHardwareParams* pHW_Params = m_currentEdittedHWFacade->GetParameters();
    m_GraphicsScene->setHardwareParams(pHW_Params);

    if (m_deviceList[0].isSimulated())
    {
        setWindowTitle ( tr("afarsek - Simulation") );
    }
    else
    {
        QString title;
        title.sprintf ("afarsek - Connected to %s Ver. %d.%d",
                       pHW_Params->m_Product,
                       pHW_Params->Version,
                       pHW_Params->SubVersion);
        setWindowTitle ( title );
    }

    // update the device list view
    UpdateDeviceList();

    m_GraphicsView = ui->OriginalPicture;
    m_GraphicsScene = new QImageProcessScene(m_GraphicsView->height(),
                                             m_GraphicsView->width(),
                                             pHW_Params);

    m_GraphicsView->setScene(m_GraphicsScene);

    m_currentDir.setPath(QDir::currentPath());

    ui->fileList->UpdateFileList();
}

//_________________________________________________________________________
Dialog::~Dialog()
{
    for (int i=0; i<m_deviceList.size(); i++)
    {
        m_deviceList[i].getHardwareFacade()->ResetDevice();
        m_deviceList[i].releaseHardwareFacade();
    }

    delete m_GraphicsScene;
    delete ui;
}

//_________________________________________________________________________
void Dialog::changeEvent(QEvent *e)
{
    QDialog::changeEvent(e);
    switch (e->type()) {
    case QEvent::LanguageChange:
        ui->retranslateUi(this);
        break;
    default:
        break;
    }
}

//_________________________________________________________________________
void Dialog::on_loadPictureButton_clicked()
{
    unsigned char *buffer = NULL;
    int bufferLength;

    ui->fileList->UpdateFileList();

    QString filename = QFileDialog::getOpenFileName(
            this,
            tr("Load Image"),
            m_currentDir.absolutePath(),
            tr("Image files (*.bmp *.jpg);;All files (*.*)") );

    if( !filename.isNull() )
    {
        qDebug( "The filename - %s - was openned.\n", filename.toAscii().data() );
        QFileInfo fi(filename);
        m_currentDir = fi.canonicalPath();

        m_GraphicsScene->SetImagePath(filename);
        m_GraphicsView->show();

        m_GraphicsScene->GetHWData(&bufferLength, &buffer);
        m_currentEdittedFileSystem->AddFile(fi.baseName().toAscii().data(), m_GraphicsScene->GetFrameWidth());
        m_currentEdittedFileSystem->AddFrameToFile (fi.baseName().toAscii().data(), bufferLength, buffer);
        m_currentEdittedFileSystem->SetOriginalImageToFile (fi.baseName().toAscii().data(), m_GraphicsScene->getLoadedImage());
        ui->fileList->UpdateFileList();
    }
}

//_________________________________________________________________________
void Dialog::UpdateDeviceList ( void )
{
    int i;

    // clear all the contents of the list
    ui->deviceList->clear();

    for (i=0; i<m_deviceList.size(); i++)
    {
        QListWidgetItem *newItem = NULL;
        char deviceName[32];
        sprintf(deviceName, "%d", i);

        if (m_deviceList[i].getDeviceType()==FOUND_MOUSSAVI && m_deviceList[i].isSimulated()==0)
            newItem = new QListWidgetItem( QIcon(":/icons/AniBikeLogoIcon"), tr(deviceName), ui->deviceList);
        if (m_deviceList[i].getDeviceType()==FOUND_MOUSSAVI && m_deviceList[i].isSimulated()==1)
            newItem = new QListWidgetItem( QIcon(":/icons/AniBikeLogoIconSim"), tr(deviceName), ui->deviceList);
        if (m_deviceList[i].getDeviceType()==FOUND_ANIBIKE && m_deviceList[i].isSimulated()==0)
            newItem = new QListWidgetItem( QIcon(":/icons/AniBikeLogoIcon"), tr(deviceName), ui->deviceList);
        if (m_deviceList[i].getDeviceType()==FOUND_ANIBIKE && m_deviceList[i].isSimulated()==1)
            newItem = new QListWidgetItem( QIcon(":/icons/AniBikeLogoIconSim"), tr(deviceName), ui->deviceList);


        if (newItem!=NULL)
            ui->deviceList->addItem(newItem);

        if (i==0)
        {
            ui->deviceList->setCurrentItem(newItem, QItemSelectionModel::Select);
        }
    }

    ui->deviceList->show();
}

//_________________________________________________________________________
void Dialog::on_SyncButton_clicked()
{
    ui->fileList->UpdateFileList();
    m_currentEdittedHWFacade->SynchronizeFileSystem (m_currentEdittedFileSystem, ui->fileList);
    ui->fileList->UpdateFileList();
}

//_________________________________________________________________________
void Dialog::on_DeleteButton_clicked()
{
    QString selectedItem = ui->fileList->DeleteSelectedFile();
    m_currentEdittedFileSystem->DeleteFileFS(selectedItem.toAscii().data());
    m_GraphicsScene->ClearScreen ();
    ui->fileList->UpdateFileList();
}

//_________________________________________________________________________
void Dialog::on_fileList_cellClicked(int row, int column)
{
    QString selectedItem = ui->fileList->selectedItems().first()->text();

    unsigned char *data = NULL;
    int length = 0;

    m_currentEdittedFileSystem->GetFileFrameData (selectedItem.toAscii ().data (), 0, &length, &data);
    QImage* image = m_currentEdittedFileSystem->GetOriginalImageToFile(selectedItem.toAscii ().data ());
    m_GraphicsScene->SetHWData(length, data);

    if (image!=NULL)
        m_GraphicsScene->setLoadedImage(*image);
}

//_________________________________________________________________________
void Dialog::on_deviceList_clicked(const QModelIndex &index)
{
    if (ui->deviceList->selectedItems().count()==0)
    {
        QListWidgetItem* item = ui->deviceList->itemAt(0,0);
        ui->deviceList->setCurrentItem(item);
    }

    QString deviceName = ui->deviceList->selectedItems().first()->text();

    int selectedDevice = deviceName.toInt();
    ui->fileList->SetCurrentDeviceNumber (selectedDevice);
    m_currentEdittedHWFacade = m_deviceList[selectedDevice].getHardwareFacade();
    m_currentEdittedFileSystem = m_deviceList[selectedDevice].getFileSystem();
    m_GraphicsScene->setHardwareParams(m_currentEdittedHWFacade->GetParameters());
    ui->fileList->SetFileSystem(m_currentEdittedFileSystem);
    m_currentEdittedHWFacade->TestLeds( );
    ui->fileList->UpdateFileList();
}

//_________________________________________________________________________
void Dialog::on_deviceList_doubleClicked(const QModelIndex &index)
{

}

void Dialog::on_deviceList_itemChanged(QListWidgetItem *item)
{

}
